package tests;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import junit.framework.Assert;

import model.Problem;
import model.SolverEnvironment;

import org.jfree.util.Log;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sun.xml.internal.ws.util.StringUtils;

import solver.BaseExtraLeanIPModelBuilder;
import solver.GrbExtraLeanIPModelBuilder;
import solver.SelectionAgent4;
import util.Importer;
import util.SolutionImporter;

public class GRBSolverConsistencyTest {
	private static Logger log = LoggerFactory
			.getLogger(GRBSolverConsistencyTest.class);

	public static void main(String[] args) {
		GRBSolverConsistencyTest app = new GRBSolverConsistencyTest();
		// app.test_dataset_model_example();
		// app.test_dataset_a2_2();
		// app.test_dataset_a2_4();// balance objective
		app.test_dataset_b6();
	}

	Importer importer;
	Problem problem;
	SolutionImporter solutionImporter;
	SolverEnvironment env;

	@Test
	public void test_dataset_model_example() {
		importer = new Importer("datasets//model_example.txt");
		problem = importer.getProblem();
		importer.readData();
		solutionImporter = new SolutionImporter(problem);
		solutionImporter
				.setSolutionFileName("solutions//assignment_example.txt");
		env = new SolverEnvironment(problem, solutionImporter.readData());
		problem.computeTransientResourcesRemainingCapacityPerMachine(env);
		long cutoff = Long.MAX_VALUE - 1;

		List<Integer> selectedProcesses = new ArrayList<Integer>();
		selectedProcesses.add(0);
		// selectedProcesses.add(1); // not selected
		selectedProcesses.add(2);
		model.Process p0 = problem.getProcesses().get(0);
		p0.addEligibleMachine(0);// initial
		p0.addEligibleMachine(1);
		// p0.addEligibleMachine(2); // not selected
		// p0.addEligibleMachine(3);// not selected
		// model.Process p1 = problem.getProcesses().get(1);// not selected
		// p1.addEligibleMachine(0);// not selected
		// p1.addEligibleMachine(1);// not selected
		// p1.addEligibleMachine(2);// not selected
		// p1.addEligibleMachine(3);// not selected
		model.Process p2 = problem.getProcesses().get(2);
		p2.addEligibleMachine(0);// initial
		p2.addEligibleMachine(1);
		// p2.addEligibleMachine(2); // not selected
		p2.addEligibleMachine(3);

		GrbExtraLeanIPModelBuilder modelBuilder = new GrbExtraLeanIPModelBuilder(
				problem, selectedProcesses, false, 5, cutoff);
		modelBuilder.setInitialSolution(env.getInitialSolution());
		modelBuilder.setCurrentSolution(env.getCurrentSolution());
		boolean saveLP = true;
		modelBuilder.solve(saveLP);

		// modelBuilder.printCostInfo();
		env.setCurrentSolution(modelBuilder.saveToSolution());
		env.getFullValidator().printCostAnalysis();
		System.out.println(Arrays.toString(modelBuilder.getCostVector()));
		System.out.println(Arrays.toString(env.getFullValidator()
				.getCostVector()));

	}

	// @Test
	public void test_dataset_a2_2() {
		int nop = 20;
		int noem = 10;
		int non = 3;
		importer = new Importer("datasets//model_a2_2.txt");
		problem = importer.getProblem();
		importer.readData();
		solutionImporter = new SolutionImporter(problem);
		solutionImporter.setSolutionFileName("solutions//assignment_a2_2.txt");
		env = new SolverEnvironment(problem, solutionImporter.readData());
		problem.computeTransientResourcesRemainingCapacityPerMachine(env);

		SelectionAgent4 sa4 = new SelectionAgent4(env);
		for (int i = 0; i < 100; i++) {
			List<Integer> selectedProcesses = sa4
					.selectFullRandomProcessesAndMachinesFast(nop, noem, non);
			long cutoff = env.getFullValidator().getNewSolutionCost();
			GrbExtraLeanIPModelBuilder modelBuilder = new GrbExtraLeanIPModelBuilder(
					problem, selectedProcesses, false, 5, cutoff);
			modelBuilder.setInitialSolution(env.getInitialSolution());
			modelBuilder.setCurrentSolution(env.getCurrentSolution());
			boolean saveLP = true;
			modelBuilder.solve(saveLP);

			// modelBuilder.printCostInfo();
			env.setCurrentSolution(modelBuilder.saveToSolution());
			env.getFullValidator().printCostAnalysis();
			long a[] = modelBuilder.getCostVector();
			long b[] = env.getFullValidator().getCostVector();

			for (int j = 0; j < a.length; j++) {
				Assert.assertEquals(a[j], b[j]);
			}

			System.out.println(Arrays.toString(modelBuilder.getCostVector()));
			System.out.println(Arrays.toString(env.getFullValidator()
					.getCostVector()));
		}
	}

	// @Test
	public void test_dataset_a2_4() {
		int nop = 20;
		int noem = 10;
		int non = 3;
		importer = new Importer("datasets//model_a2_4.txt");
		problem = importer.getProblem();
		importer.readData();
		solutionImporter = new SolutionImporter(problem);
		solutionImporter.setSolutionFileName("solutions//assignment_a2_4.txt");
		env = new SolverEnvironment(problem, solutionImporter.readData());
		problem.computeTransientResourcesRemainingCapacityPerMachine(env);

		SelectionAgent4 sa4 = new SelectionAgent4(env);
		for (int i = 0; i < 100; i++) {
			List<Integer> selectedProcesses = sa4
					.selectFullRandomProcessesAndMachinesFast(nop, noem, non);
			long cutoff = env.getFullValidator().getNewSolutionCost();
			GrbExtraLeanIPModelBuilder modelBuilder = new GrbExtraLeanIPModelBuilder(
					problem, selectedProcesses, false, 5, cutoff);
			modelBuilder.setInitialSolution(env.getInitialSolution());
			modelBuilder.setCurrentSolution(env.getCurrentSolution());
			boolean saveLP = true;
			modelBuilder.solve(saveLP);

			// modelBuilder.printCostInfo();
			env.setCurrentSolution(modelBuilder.saveToSolution());
			env.getFullValidator().printCostAnalysis();
			long a[] = modelBuilder.getCostVector();
			long b[] = env.getFullValidator().getCostVector();

			// for (int j = 0; j < a.length; j++) {
			// Assert.assertEquals(a[j], b[j]);
			// }

			System.out.println(Arrays.toString(modelBuilder.getCostVector()));
			System.out.println(Arrays.toString(env.getFullValidator()
					.getCostVector()));
		}
	}

	@Test
	public void test_dataset_a1_2() {
		int nop = 30;
		int noem = 15;
		int non = 2;
		importer = new Importer("datasets//model_a1_2.txt");
		problem = importer.getProblem();
		importer.readData();
		solutionImporter = new SolutionImporter(problem);
		solutionImporter.setSolutionFileName("solutions//assignment_a1_2.txt");
		env = new SolverEnvironment(problem, solutionImporter.readData());
		problem.computeTransientResourcesRemainingCapacityPerMachine(env);

		SelectionAgent4 sa4 = new SelectionAgent4(env);
		for (int i = 0; i < 100; i++) {
			List<Integer> selectedProcesses = sa4
					.selectFullRandomProcessesAndMachinesFast(nop, noem, non);
			long cutoff = env.getFullValidator().getNewSolutionCost();
			GrbExtraLeanIPModelBuilder modelBuilder = new GrbExtraLeanIPModelBuilder(
					problem, selectedProcesses, false, 5, cutoff);
			modelBuilder.setInitialSolution(env.getInitialSolution());
			modelBuilder.setCurrentSolution(env.getCurrentSolution());
			boolean saveLP = true;
			modelBuilder.solve(saveLP);

			// modelBuilder.printCostInfo();
			env.setCurrentSolution(modelBuilder.saveToSolution());
			env.getFullValidator().printCostAnalysis();
			long a[] = modelBuilder.getCostVector();
			long b[] = env.getFullValidator().getCostVector();

			for (int j = 0; j < a.length; j++) {
				Assert.assertEquals(a[j], b[j]);
			}

			System.out.println(Arrays.toString(modelBuilder.getCostVector()));
			System.out.println(Arrays.toString(env.getFullValidator()
					.getCostVector()));
		}
	}

	// @Test
	public void test_dataset_b6() {
		int nop = 3;
		int noem = 2;
		int non = 2;
		importer = new Importer("datasets//model_b_6.txt");
		problem = importer.getProblem();
		importer.readData();
		solutionImporter = new SolutionImporter(problem);
		solutionImporter.setSolutionFileName("solutions//assignment_b_6.txt");
		env = new SolverEnvironment(problem, solutionImporter.readData());
		problem.computeTransientResourcesRemainingCapacityPerMachine(env);

		SelectionAgent4 sa4 = new SelectionAgent4(env);
		sa4.setDependencyConstraintsNeeded(false);
		for (int i = 0; i < 100; i++) {
			log.debug("--------------->ROUND " + i);
			List<Integer> selectedProcesses = sa4
					.selectFullRandomProcessesAndMachinesFast(nop, noem, non);
			long cutoff = env.getFullValidator().getNewSolutionCost();
			System.out.println("\n"
					+ problem.getSelectedProcessesAndEligibleMachines(
							selectedProcesses, true, env));
			GrbExtraLeanIPModelBuilder modelBuilder = new GrbExtraLeanIPModelBuilder(
					problem, selectedProcesses, false, 5, cutoff);
			modelBuilder.setInitialSolution(env.getInitialSolution());
			modelBuilder.setCurrentSolution(env.getCurrentSolution());
//			modelBuilder.includeDependencyHardConstraints(false);
			boolean saveLP = true;
			modelBuilder.solve(saveLP);
			// modelBuilder.printCostInfo();
			env.setCurrentSolution(modelBuilder.saveToSolution());
			env.getProblem().VERBOSE = true;
			if (env.getFullValidator().isFeasible()) {
				log.debug("Solution feasible :)");
			} else {
				log.debug("Solution infeasible :(");
				System.exit(-1);
			}
			env.getFullValidator().printCostAnalysis();
			long a[] = modelBuilder.getCostVector();
			long b[] = env.getFullValidator().getCostVector();

			// for (int j = 0; j < a.length; j++) {
			// Assert.assertEquals(a[j], b[j]);
			// }

			log.debug(Arrays.toString(modelBuilder.getCostVector()));
			log.debug(Arrays.toString(env.getFullValidator().getCostVector()));
			log.debug(org.apache.commons.lang3.StringUtils.repeat("#", 40));
		}
	}

}
